home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / os2 / gnuwget.zip / wget-1.4.3 / src / ftp.c < prev    next >
C/C++ Source or Header  |  1997-02-08  |  40KB  |  1,580 lines

  1. /* File Transfer Protocol support.
  2.    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
  3.    
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.    
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.    
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18.  
  19. #ifdef HAVE_CONFIG_H
  20. #  include <config.h>
  21. #endif /* HAVE_CONFIG_H */
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #ifdef HAVE_STRING_H
  26. #  include <string.h>
  27. #else
  28. #  include <strings.h>
  29. #endif
  30. #include <ctype.h>
  31. #ifdef HAVE_UNISTD_H
  32. #  include <unistd.h>
  33. #endif
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36.  
  37. #ifdef WINDOWS
  38. # include <winsock.h>
  39. #else
  40. # include <netinet/in.h>
  41. #endif /* WINDOWS */
  42.  
  43.  
  44. #include <assert.h>
  45.  
  46. #include "wget.h"
  47. #include "options.h"
  48. #include "utils.h"
  49. #include "url.h"
  50. #include "ftp.h"
  51. #include "ftp-basic.h"
  52. #include "html.h"
  53. #include "connect.h"
  54. #include "host.h"
  55. #include "http.h"
  56. #include "mtch.h"
  57. #include "retr.h"
  58. #include "netrc.h"
  59.  
  60. extern struct options opt;
  61. extern char ftp_last_respline[128];
  62.  
  63. #ifndef errno
  64. extern int errno;
  65. #endif
  66. #ifndef h_errno
  67. extern int h_errno;
  68. #endif
  69.  
  70. /* Retrieves a file with denoted parameters through opening an FTP
  71.    connection to the server.  It always closes the data connection,
  72.    and closes the control connection in case of error.  */
  73. uerr_t
  74. getftp(const urlinfo *u, long *len, long restval, ccon *con)
  75. {
  76.    int csock, dtsock, res;
  77.    uerr_t err;
  78.    FILE *fp;
  79.    char *user, *passwd, *respline;
  80.    char *tms, *tmrate;
  81.    unsigned char pasv_addr[6];
  82.    int cmd = con->cmd;
  83.    int passive_mode_open= 0;
  84.    long expected_bytes = 0L;
  85.  
  86.    assert(con != NULL);
  87.    assert(u->local != NULL);
  88.    /* Debug-check of the sanity of the request:
  89.       Make sure that not both LIST and RETR are requested (since we
  90.       can handle only one at a time. */
  91.    assert(!((cmd & DO_LIST) && (cmd & DO_RETR)));
  92.    /* Make sure that at least *something* is requested. */
  93.    assert((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
  94.  
  95.    user = u->user;
  96.    passwd = u->passwd;
  97.    search_netrc(u->host, (const char **)&user, (const char **)&passwd, 1);
  98.    user = user ? user : opt.ftp_acc;
  99.    passwd = passwd ? passwd : opt.ftp_pass;
  100.    assert(user && passwd);
  101.  
  102.    dtsock = -1;
  103.    con->dltime = 0;
  104.  
  105.    if (!(cmd & DO_LOGIN))
  106.       csock = con->fd;
  107.    else                         /* cmd & DO_LOGIN */
  108.    {
  109.       /* Login to the server: */
  110.       
  111.       /* First: Establish the control connection. */
  112.       if (opt.verbose)
  113.      fprintf(opt.lfile, "Connecting to %s:%hu... ", u->host, u->port);
  114.       err = make_connection(&csock, u->host, u->port);
  115.       if (cmd & LEAVE_PENDING)
  116.      con->fd = csock;
  117.       else
  118.      con->fd = -1;
  119.       switch (err)
  120.       {
  121.      /* Do not close the socket in first several cases,
  122.         since it wasn't created at all. */
  123.      case HOSTERR:
  124.         if (!opt.quiet)
  125.         {
  126.            if (opt.verbose)
  127.           fprintf(opt.lfile, "\n");
  128.            fprintf(opt.lfile, "%s: %s\n", u->host, herrmsg(h_errno));
  129.         }
  130.         return HOSTERR;
  131.         break;
  132.      case CONSOCKERR:
  133.         if (!opt.quiet)
  134.         {
  135.            if (opt.verbose)
  136.           fprintf(opt.lfile, "\n");
  137.            fprintf(opt.lfile, "socket: %s\n", mystrerror(errno));
  138.         }
  139.         return CONSOCKERR;
  140.         break;
  141.      case CONREFUSED:
  142.         if (!opt.quiet)
  143.         {
  144.            if (opt.verbose)
  145.           fprintf(opt.lfile, "\n");
  146.            fprintf(opt.lfile, "Connection to %s:%hu refused.\n", u->host,
  147.                u->port);
  148.         }
  149.         CLOSE(csock);
  150.         con->fd = -1;
  151.         return CONREFUSED;
  152.      case CONERROR:
  153.         if (!opt.quiet)
  154.         {
  155.            if (opt.verbose)
  156.           fprintf(opt.lfile, "\n");
  157.            fprintf(opt.lfile, "connect: %s\n", mystrerror(errno));
  158.         }
  159.         CLOSE(csock);
  160.         con->fd = -1;
  161.         return CONERROR;
  162.         break;
  163.       }
  164.       /* Since this is a new connection, we may safely discard
  165.      anything left in the buffer. */
  166.       buf_discard();
  167.       
  168.       /* Second: Login with proper USER/PASS sequence. */
  169.       if (opt.verbose)
  170.       {
  171.      fprintf(opt.lfile, "connected!\n");
  172.      fprintf(opt.lfile, "Logging in as %s ... ", user);
  173.      if (opt.server_response)
  174.         fputc('\n', opt.lfile);
  175.       }
  176.       err = ftp_login(csock, user, passwd);
  177.       /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC. */
  178.       switch (err)
  179.       {
  180.      case FTPRERR:
  181.         if (!opt.quiet)
  182.         {
  183.            if (opt.verbose)
  184.           fprintf(opt.lfile, "\n");
  185.            fprintf(opt.lfile, "Error in server response, closing control connection.\n");
  186.         }
  187.         CLOSE(csock);
  188.         con->fd = -1;
  189.         return err;
  190.         break;
  191.      case FTPSRVERR:
  192.         if (!opt.quiet)
  193.         {
  194.            if (opt.verbose)
  195.           fprintf(opt.lfile, "\n");
  196.            fprintf(opt.lfile, "Error in server greeting.\n");
  197.         }
  198.         CLOSE(csock);
  199.         con->fd = -1;
  200.         return err;
  201.      case WRITEFAILED:
  202.         if (!opt.quiet)
  203.         {
  204.            if (opt.verbose)
  205.           fprintf(opt.lfile, "\n");
  206.            fprintf(opt.lfile,
  207.                "Write failed, closing control connection.\n");
  208.         }
  209.         CLOSE(csock);
  210.         con->fd = -1;
  211.         return err;
  212.         break;
  213.      case FTPLOGREFUSED:
  214.         if (!opt.quiet)
  215.         {
  216.            if (opt.verbose)
  217.           fprintf(opt.lfile, "\n");
  218.            fprintf(opt.lfile, "The server refuses login.\n");
  219.         }
  220.         CLOSE(csock);
  221.         con->fd = -1;
  222.         return FTPLOGREFUSED;
  223.         break;
  224.      case FTPLOGINC:
  225.         if (!opt.quiet)
  226.         {
  227.            if (opt.verbose)
  228.           fprintf(opt.lfile, "\n");
  229.            fprintf(opt.lfile, "Login incorrect.\n");
  230.         }
  231.         CLOSE(csock);
  232.         con->fd = -1;
  233.         return FTPLOGINC;
  234.         break;
  235.      case FTPOK:
  236.         if (opt.verbose && !opt.server_response)
  237.            fprintf(opt.lfile, "Logged in!\n");
  238.         break;
  239.      default:
  240.         assert(0);
  241.         exit(1);
  242.         break;
  243.       }
  244.       /* Third: Set type to Image (binary). */
  245.       if (opt.verbose && !opt.server_response)
  246.      fprintf(opt.lfile, "==> TYPE I ... ");
  247.       err = ftp_type(csock, 'I');
  248.       /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE. */
  249.       switch (err)
  250.       {
  251.      case FTPRERR:
  252.         if (!opt.quiet)
  253.         {
  254.            if (opt.verbose)
  255.           fprintf(opt.lfile, "\n");
  256.            fprintf(opt.lfile, "Error in server response, closing control connection.\n");
  257.         }
  258.         CLOSE(csock);
  259.         con->fd = -1;
  260.         return err;
  261.         break;
  262.      case WRITEFAILED:
  263.         if (!opt.quiet)
  264.         {
  265.            if (opt.verbose)
  266.           fprintf(opt.lfile, "\n");
  267.            fprintf(opt.lfile,
  268.                "Write failed, closing control connection.\n");
  269.         }
  270.         CLOSE(csock);
  271.         con->fd = -1;
  272.         return err;
  273.         break;
  274.      case FTPUNKNOWNTYPE:
  275.         if (!opt.quiet)
  276.         {
  277.            if (opt.verbose)
  278.           fprintf(opt.lfile, "\n");
  279.            fprintf(opt.lfile,
  280.                "Unknown type(?), closing control connection.\n");
  281.         }
  282.         CLOSE(csock);
  283.         con->fd = -1;
  284.         return err;
  285.      case FTPOK:
  286.         /* Everything is OK. */
  287.         break;
  288.      default:
  289.         assert(0);
  290.         break;
  291.       }
  292.       if (opt.verbose && !opt.server_response)
  293.      fprintf(opt.lfile, "done.  ");
  294.    } /* do login */
  295.    
  296.    if (cmd & DO_CWD)
  297.    {
  298.       if (!*u->dir)
  299.       {
  300.      if (opt.verbose)
  301.         fprintf(opt.lfile, "==> CWD not needed.\n");
  302.       }
  303.       else
  304.       {
  305.      /* Change working directory. */
  306.      if (opt.verbose && !opt.server_response)
  307.         fprintf(opt.lfile, "==> CWD %s ... ", u->dir);
  308.      err = ftp_cwd(csock, u->dir);
  309.      /* FTPRERR, WRITEFAILED, FTPNSFOD */
  310.      switch (err)
  311.      {
  312.         case FTPRERR:
  313.            if (!opt.quiet)
  314.            {
  315.           if (opt.verbose)
  316.              fprintf(opt.lfile, "\n");
  317.           fprintf(opt.lfile,
  318.               "Error in server response, closing control connection.\n");
  319.            }
  320.            CLOSE(csock);
  321.            con->fd = -1;
  322.            return err;
  323.            break;
  324.         case WRITEFAILED:
  325.            if (!opt.quiet)
  326.            {
  327.           if (opt.verbose)
  328.              fprintf(opt.lfile, "\n");
  329.           fprintf(opt.lfile,
  330.               "Write failed, closing control connection.\n");
  331.            }
  332.            CLOSE(csock);
  333.            con->fd = -1;
  334.            return err;
  335.            break;
  336.         case FTPNSFOD:
  337.            if (!opt.quiet)
  338.            {
  339.           if (opt.verbose)
  340.              fprintf(opt.lfile, "\n");
  341.           fprintf(opt.lfile, "No such directory `%s'.\n\n", u->dir);
  342.            }
  343.            CLOSE(csock);
  344.            con->fd = -1;
  345.            return err;
  346.            break;
  347.         case FTPOK:
  348.            /* fine and dandy */
  349.            break;
  350.         default:
  351.            assert(0);
  352.            break;
  353.      }
  354.      if (opt.verbose && !opt.server_response)
  355.         fprintf(opt.lfile, "done.\n");
  356.       }
  357.    }
  358.    else /* do not CWD */
  359.    {
  360.       if (opt.verbose)
  361.      fprintf(opt.lfile, "==> CWD not required.\n");
  362.    }
  363.    
  364.    /* If anything is to be retrieved, PORT (or PASV) must be sent. */
  365.    if (cmd & (DO_LIST | DO_RETR))
  366.    {
  367.       if (opt.ftp_pasv)
  368.       {
  369.      char thost[256];
  370.      unsigned short tport;
  371.  
  372.      if (opt.verbose && !opt.server_response)
  373.         fprintf(opt.lfile, "==> PASV ... ");
  374.      err = ftp_pasv(csock, pasv_addr);
  375.      /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
  376.      switch(err)
  377.      {
  378.         case FTPRERR:
  379.            if (!opt.quiet)
  380.            {
  381.           if (opt.verbose)
  382.              fprintf(opt.lfile, "\n");
  383.           fprintf(opt.lfile, "Error in server response, closing control connection.\n");
  384.            }
  385.            CLOSE(csock);
  386.            con->fd = -1;
  387.            return err;
  388.            break;
  389.         case WRITEFAILED:
  390.            if (!opt.quiet)
  391.            {
  392.           if (opt.verbose)
  393.              fprintf(opt.lfile, "\n");
  394.           fprintf(opt.lfile,
  395.               "Write failed, closing control connection.\n");
  396.            }
  397.            CLOSE(csock);
  398.            con->fd = -1;
  399.            return err;
  400.            break;
  401.         case FTPNOPASV:
  402.            if (!opt.quiet)
  403.            {
  404.           if (opt.verbose)
  405.              fprintf(opt.lfile, "\n");
  406.           fprintf(opt.lfile, "Cannot initiate PASV transfer.\n");
  407.            }
  408.            break;
  409.         case FTPINVPASV:
  410.            if (!opt.quiet)
  411.            {
  412.           if (opt.verbose)
  413.              fprintf(opt.lfile, "\n");
  414.           fprintf(opt.lfile, "Cannot parse PASV response.\n");
  415.            }
  416.            break;
  417.         case FTPOK:
  418.            /* fine and dandy */
  419.            break;
  420.         default:
  421.            assert(0);
  422.            break;
  423.      }
  424.      if (err==FTPOK)
  425.      {
  426.         sprintf(thost, "%d.%d.%d.%d",
  427.             pasv_addr[0], pasv_addr[1], pasv_addr[2], pasv_addr[3]);
  428.         tport = (pasv_addr[4] << 8) + pasv_addr[5];
  429. #ifdef DEBUG
  430.         if (opt.debug)
  431.         fprintf(opt.lfile, "Will try connecting to %s:%hu.\n", thost,
  432.             tport);
  433. #endif
  434.         err = make_connection(&dtsock, thost, tport);
  435.         switch (err)
  436.         {
  437.            /* Do not close the socket in first several cases,
  438.               since it wasn't created at all. */
  439.          case HOSTERR:
  440.            if (!opt.quiet)
  441.            {
  442.               if (opt.verbose)
  443.               fprintf(opt.lfile, "\n");
  444.               fprintf(opt.lfile, "%s: %s\n", thost, herrmsg(h_errno));
  445.            }
  446.            CLOSE(csock);
  447.            con->fd = -1;
  448.            return HOSTERR;
  449.            break;
  450.          case CONSOCKERR:
  451.            if (!opt.quiet)
  452.            {
  453.               if (opt.verbose)
  454.               fprintf(opt.lfile, "\n");
  455.               fprintf(opt.lfile, "socket: %s\n", mystrerror(errno));
  456.            }
  457.            CLOSE(csock);
  458.            con->fd = -1;
  459.            return CONSOCKERR;
  460.            break;
  461.          case CONREFUSED:
  462.            if (!opt.quiet)
  463.            {
  464.               if (opt.verbose)
  465.               fprintf(opt.lfile, "\n");
  466.               fprintf(opt.lfile, "Connection to %s:%hu refused.\n",
  467.                   thost, tport);
  468.            }
  469.            CLOSE(csock);
  470.            con->fd = -1;
  471.            closeport(dtsock);
  472.            return CONREFUSED;
  473.          case CONERROR:
  474.            if (!opt.quiet)
  475.            {
  476.               if (opt.verbose)
  477.               fprintf(opt.lfile, "\n");
  478.               fprintf(opt.lfile, "connect: %s\n", mystrerror(errno));
  479.            }
  480.            CLOSE(csock);
  481.            con->fd = -1;
  482.            closeport(dtsock);
  483.            return CONERROR;
  484.            break;
  485.         }
  486.         passive_mode_open= 1;  /* Flag to avoid accept port */
  487.         if (opt.verbose && !opt.server_response)
  488.         fprintf(opt.lfile, "done.    ");
  489.      } /* err==FTP_OK */
  490.       }
  491.  
  492.       if (!passive_mode_open)   /* Try to use a port command if PASV failed */
  493.       {
  494.      if (opt.verbose && !opt.server_response)
  495.          fprintf(opt.lfile, "==> PORT ... ");
  496.      err = ftp_port(csock);
  497.      /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
  498.         LISTENERR), HOSTERR, FTPPORTERR */
  499.      switch(err)
  500.          {
  501.           case FTPRERR:
  502.         if (!opt.quiet)
  503.             {
  504.                if (opt.verbose)
  505.                fprintf(opt.lfile, "\n");
  506.                fprintf(opt.lfile, "Error in server response, closing control connection.\n");
  507.             }
  508.         CLOSE(csock);
  509.         closeport(dtsock);
  510.         con->fd = -1;
  511.         return err;
  512.         break;
  513.           case WRITEFAILED:
  514.         if (!opt.quiet)
  515.             {
  516.                if (opt.verbose)
  517.                fprintf(opt.lfile, "\n");
  518.                fprintf(opt.lfile,
  519.                    "Write failed, closing control connection.\n");
  520.             }
  521.         CLOSE(csock);
  522.         closeport(dtsock);
  523.         con->fd = -1;
  524.         return err;
  525.         break;
  526.           case CONSOCKERR:
  527.         if (!opt.quiet)
  528.             {
  529.                if (opt.verbose)
  530.                fprintf(opt.lfile, "\n");
  531.                fprintf(opt.lfile, "socket: %s\n", mystrerror(errno));
  532.             }
  533.         CLOSE(csock);
  534.         closeport(dtsock);
  535.         con->fd = -1;
  536.         return err;
  537.         break;
  538.           case CONPORTERR: case BINDERR: case LISTENERR:
  539.         /* What now? These are local troubles... */
  540.         if (!opt.quiet)
  541.             {
  542.                if (opt.verbose)
  543.                fprintf(opt.lfile, "\n");
  544.                fprintf(opt.lfile, "Bind error (%s).\n", mystrerror(errno));
  545.             }
  546.         closeport(dtsock);
  547.         return err;
  548.         break;
  549.           case HOSTERR:
  550.         if (!opt.quiet)
  551.             {
  552.                if (opt.verbose)
  553.                fprintf(opt.lfile, "\n");
  554.                fprintf(opt.lfile, "%s: %s\n", u->host, herrmsg(h_errno));
  555.             }
  556.         CLOSE(csock);
  557.         closeport(dtsock);
  558.         con->fd = -1;
  559.         return HOSTERR;
  560.         break;
  561.           case FTPPORTERR:
  562.         if (!opt.quiet)
  563.             {
  564.                if (opt.verbose)
  565.                fprintf(opt.lfile, "\n");
  566.                fprintf(opt.lfile, "Invalid PORT.\n");
  567.             }
  568.         CLOSE(csock);
  569.         closeport(dtsock);
  570.         con->fd = -1;
  571.         return err;
  572.         break;
  573.           case FTPOK:
  574.         /* fine and dandy */
  575.         break;
  576.           default:
  577.         assert(0);
  578.         break;
  579.          } /* port switch */
  580.      if (opt.verbose && !opt.server_response)
  581.          fprintf(opt.lfile, "done.    ");
  582.       } /* dtsock==-1 */
  583.    } /* cmd & (DO_LIST | DO_RETR) */
  584.    
  585.    /* Restart if needed. */
  586.    if (restval && (cmd & DO_RETR))
  587.    {
  588.       if (opt.verbose && !opt.server_response)
  589.      fprintf(opt.lfile, "==> REST %ld ... ", restval);
  590.       err = ftp_rest(csock, restval);
  591.       
  592.       /* FTPRERR, WRITEFAILED, FTPRESTFAIL. */
  593.       switch (err)
  594.       {
  595.      case FTPRERR:
  596.         if (!opt.quiet)
  597.         {
  598.            if (opt.verbose)
  599.           fprintf(opt.lfile, "\n");
  600.            fprintf(opt.lfile, "Error in server response, closing control connection.\n");
  601.         }
  602.         CLOSE(csock);
  603.         closeport(dtsock);
  604.         con->fd = -1;
  605.         return err;
  606.         break;
  607.      case WRITEFAILED:
  608.         if (!opt.quiet)
  609.         {
  610.            if (opt.verbose)
  611.           fprintf(opt.lfile, "\n");
  612.            fprintf(opt.lfile,
  613.                "Write failed, closing control connection.\n");
  614.         }
  615.         CLOSE(csock);
  616.         closeport(dtsock);
  617.         con->fd = -1;
  618.         return err;
  619.         break;
  620.      case FTPRESTFAIL:
  621.         if (opt.verbose)
  622.            fprintf(opt.lfile, "\nREST failed, starting from scratch.\n");
  623.         restval = 0L;
  624.         break;
  625.      case FTPOK:
  626.         /* fine and dandy */
  627.         break;
  628.      default:
  629.         assert(0);
  630.         break;
  631.       }
  632.       if (opt.verbose)
  633.       {
  634.      if (err != FTPRESTFAIL && !opt.server_response)
  635.         fprintf(opt.lfile, "done.    ");
  636.       }
  637.    } /* restval && cmd & DO_RETR */
  638.    
  639.    if (cmd & DO_RETR)
  640.    {
  641.       if (opt.verbose)
  642.       {
  643.      if (!opt.server_response)
  644.      {
  645.         if (restval)
  646.            fprintf(opt.lfile, "\n");
  647.         fprintf(opt.lfile, "==> RETR %s ... ", u->file);
  648.      }
  649.       }
  650.       err = ftp_retr(csock, u->file);
  651.       /* FTPRERR, WRITEFAILED, FTPNSFOD */
  652.       switch (err)
  653.       {
  654.      case FTPRERR:
  655.         if (!opt.quiet)
  656.         {
  657.            if (opt.verbose)
  658.           fprintf(opt.lfile, "\n");
  659.            fprintf(opt.lfile, "Error in server response, closing control connection.\n");
  660.         }
  661.         CLOSE(csock);
  662.         closeport(dtsock);
  663.         con->fd = -1;
  664.         return err;
  665.         break;
  666.      case WRITEFAILED:
  667.         if (!opt.quiet)
  668.         {
  669.            if (opt.verbose)
  670.           fprintf(opt.lfile, "\n");
  671.            fprintf(opt.lfile,
  672.                "Write failed, closing control connection.\n");
  673.         }
  674.         CLOSE(csock);
  675.         closeport(dtsock);
  676.         con->fd = -1;
  677.         return err;
  678.         break;
  679.      case FTPNSFOD:
  680.         if (!opt.quiet)
  681.         {
  682.            if (opt.verbose)
  683.           fprintf(opt.lfile, "\n");
  684.            fprintf(opt.lfile, "No such file `%s'.\n\n", u->file);
  685.         }
  686.         closeport(dtsock);
  687.         return err;
  688.         break;
  689.      case FTPOK:
  690.         /* fine and dandy */
  691.         break;
  692.      default:
  693.         assert(0);
  694.         break;
  695.       }
  696.       
  697.       if (opt.verbose && !opt.server_response)
  698.      fprintf(opt.lfile, "done.\n");
  699.       expected_bytes = ftp_expected_bytes(ftp_last_respline);
  700.    } /* do retrieve */
  701.  
  702.    if (cmd & DO_LIST)
  703.    {
  704.       if (opt.verbose && !opt.server_response)
  705.      fprintf(opt.lfile, "==> LIST     ");
  706.       /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
  707.      without arguments is better than `LIST .'; confirmed by
  708.      RFC959.  */
  709.       err = ftp_list(csock, NULL);
  710.       /* FTPRERR, WRITEFAILED */
  711.       switch (err)
  712.       {
  713.      case FTPRERR:
  714.         if (!opt.quiet)
  715.         {
  716.            if (opt.verbose)
  717.           fprintf(opt.lfile, "\n");
  718.            fprintf(opt.lfile, "Error in server response, closing control connection.\n");
  719.         }
  720.         CLOSE(csock);
  721.         closeport(dtsock);
  722.         con->fd = -1;
  723.         return err;
  724.         break;
  725.      case WRITEFAILED:
  726.         if (!opt.quiet)
  727.         {
  728.            if (opt.verbose)
  729.           fprintf(opt.lfile, "\n");
  730.            fprintf(opt.lfile,
  731.                "Write failed, closing control connection.\n");
  732.         }
  733.         CLOSE(csock);
  734.         closeport(dtsock);
  735.         con->fd = -1;
  736.         return err;
  737.         break;
  738.      case FTPNSFOD:
  739.         if (!opt.quiet)
  740.         {
  741.            if (opt.verbose)
  742.           fprintf(opt.lfile, "\n");
  743.            fprintf(opt.lfile, "No such file or directory `%s'.\n\n", ".");
  744.         }
  745.         closeport(dtsock);
  746.         return err;
  747.         break;
  748.      case FTPOK:
  749.         /* fine and dandy */
  750.         break;
  751.      default:
  752.         assert(0);
  753.         break;
  754.       }
  755.       if (opt.verbose && !opt.server_response)
  756.      fprintf(opt.lfile, "done.\n");
  757.       expected_bytes = ftp_expected_bytes(ftp_last_respline);
  758.    } /* cmd & DO_LIST */
  759.  
  760.    /* If no transmission was required, then everything is OK. */
  761.    if (!(cmd & (DO_LIST | DO_RETR)))
  762.       return RETRFINISHED;
  763.  
  764.    if (!passive_mode_open)  /* We are not using pasive mode so we need to accept */
  765.    {
  766.       /* Open the data transmission socket by calling acceptport. */
  767.       err = acceptport(&dtsock);
  768.       /* Possible errors: ACCEPTERR. */
  769.       if (err == ACCEPTERR)
  770.       {
  771.      if (!opt.quiet)
  772.         fprintf(opt.lfile, "accept: %s\n", mystrerror(errno));
  773.      return err;
  774.       }
  775.    }
  776.    
  777.    /* Open the file -- if opt.dfp is set, use it instead. */
  778.    if (!opt.dfp || con->cmd & DO_LIST)
  779.    {
  780.       mkalldirs(u->local);
  781.       fp = fopen(u->local, restval ? "ab" : "wb");
  782.       if (!fp)
  783.       {
  784.      if (!opt.quiet)
  785.         fprintf(opt.lfile, "%s: %s\n", u->local, mystrerror(errno));
  786.      CLOSE(csock);
  787.      con->fd = -1;
  788.      closeport(dtsock);
  789.      return FOPENERR;
  790.       }
  791.    }
  792.    else
  793.       fp = opt.dfp;
  794.  
  795.    if (opt.verbose)
  796.    {
  797.       if (*len)
  798.       {
  799.      fprintf(opt.lfile, "Length: %s", legible(*len));
  800.      if (restval)
  801.         fprintf(opt.lfile, " [%s to go]", legible(*len - restval));
  802.      putc('\n', opt.lfile);
  803.       }
  804.       else if (expected_bytes)
  805.       {
  806.      fprintf(opt.lfile, "Length: %s", legible(expected_bytes));
  807.      if (restval)
  808.         fprintf(opt.lfile, " [%s to go]", legible(expected_bytes - restval));
  809.      fprintf(opt.lfile, " (unauthoritative)\n");
  810.       }
  811.    } /* opt.verbose */
  812.    reset_timer();
  813.    /* Get the contents of the document. */
  814.    res = get_contents(dtsock, fp, len, restval, 1);
  815.    con->dltime = elapsed_time();
  816.    tms = time_str(NULL);
  817.    tmrate = rate(*len - restval, con->dltime);
  818.    /* Close data connection socket. */
  819.    closeport(dtsock);
  820.    /* Close the local file. */
  821.    if (!opt.dfp || con->cmd & DO_LIST)
  822.       fclose(fp);
  823.    else
  824.       fflush(fp);
  825.    /* If get_contents couldn't write to fp, bail out. */
  826.    if (res == -2)
  827.    {
  828.       if (!opt.quiet)
  829.      fprintf(opt.lfile, "%s: %s, closing control connection.\n",
  830.          u->local, mystrerror(errno));
  831.       CLOSE(csock);
  832.       con->fd = -1;
  833.       return FWRITEERR;
  834.    }
  835.    else if (res == -1)
  836.    {
  837.       if (!opt.quiet)
  838.       {
  839.      fprintf(opt.lfile, "%s (%s) - Data connection: %s; ",
  840.          tms, tmrate, mystrerror(errno));
  841.      if (opt.server_response)
  842.         fputc('\n', opt.lfile);
  843.       }
  844.    }
  845.  
  846.    /* Get the server to tell us if everything is retrieved. */
  847.    err = ftp_response(csock, &respline);
  848.    /* ...and empty the buffer. */
  849.    buf_discard();
  850.    if (err != FTPOK)
  851.    {
  852.       free(respline);
  853.       if (!opt.quiet)
  854.       {
  855.      /* The control connection is decidedly closed.  Print the
  856.         time only if it hasn't already been printed. */
  857.      if (res != -1)
  858.         fprintf(opt.lfile, "%s (%s) - ", tms, tmrate);
  859.      fprintf(opt.lfile, "Control connection closed.\n");
  860.       }
  861.       /* If there is an error on the control connection, close it, but
  862.      return FTPRETRINT, since there is a possibility that the
  863.      whole file was retrieved nevertheless (but that is for
  864.      ftp_loop_internal to decide).  */
  865.       CLOSE(csock);
  866.       con->fd = -1;
  867.       return FTPRETRINT;
  868.    } /* err != FTPOK */
  869.    /* If retrieval failed for any reason, return FTPRETRINT, but do
  870.       not close socket, since the control connection is still
  871.       alive. If there is something wrong with the c. connection, it
  872.       will become apparent later. */
  873.    if (*respline != '2')
  874.    {
  875.       free(respline);
  876.       if (res != -1)
  877.      fprintf(opt.lfile, "%s (%s) - ", tms, tmrate);
  878.       fprintf(opt.lfile, "Data transfer aborted.\n");
  879.       return FTPRETRINT;
  880.    }
  881.    free(respline);
  882.  
  883.    if (res == -1)
  884.    {
  885.       /* What now? The data connection was erroneous, whereas the
  886.      response says everything is OK. We shall play it safe. */
  887.       return FTPRETRINT;
  888.    }
  889.  
  890.    if (!(cmd & LEAVE_PENDING))
  891.    {
  892.       /* I should probably send 'QUIT' and check for a reply, but this
  893.      is faster. :-) */
  894.       CLOSE(csock);
  895.       con->fd = -1;
  896.    }
  897.    /* If it was a listing, and opt.server_response is true,
  898.       print it out. */
  899.    if (opt.server_response && (con->cmd & DO_LIST))
  900.    {
  901.       mkalldirs(u->local);
  902.       fp = fopen(u->local, "r");
  903.       if (!fp)
  904.       {
  905.      if (!opt.quiet)
  906.         fprintf(opt.lfile, "%s: %s\n", u->local, mystrerror(errno));
  907.       }
  908.       else
  909.       {
  910.      char *line;
  911.      /* The lines are being read with read_whole_line because of
  912.         no-buffering on opt.lfile. */
  913.      while ((line = read_whole_line(fp)))
  914.      {
  915.         fprintf(opt.lfile, "%s\n", line);
  916.         free(line);
  917.      }
  918.      fclose(fp);
  919.       }
  920.    } /* con->cmd & DO_LIST && server_response */
  921.    
  922.    return RETRFINISHED;
  923. }
  924.  
  925. /* A one-file FTP loop. This is the part where FTP retrieval is
  926.    retried, and retried, and retried, and...
  927.  
  928.    This loop either gets commands from con, or (if ON_YOUR_OWN is
  929.    set), makes them up to retrieve the file given by the URL. */
  930. uerr_t
  931. ftp_loop_internal(urlinfo *u, struct fileinfo *f, ccon *con)
  932. {
  933.    static int first_retrieval = 1;
  934.  
  935.    int count, orig_lp;
  936.    long restval, len;
  937.    char *tms, *tmrate, *locf;
  938.    uerr_t err;
  939.    struct stat st;
  940.  
  941.    if (!u->local)
  942.       u->local = url_filename(u);
  943.  
  944.    if (opt.noclobber && exists(u->local))
  945.    {
  946.       if (opt.verbose)
  947.      fprintf(opt.lfile, "File `%s' already there, not retrieving.\n",
  948.          u->local);
  949.       /* If the file is there, we suppose it's retrieved OK. */
  950.       return RETROK;
  951.    }
  952.    
  953.    /* Remove it if it's a link. */
  954.    remove_link(u->local);
  955.    if (!opt.output_document)
  956.       locf = u->local;
  957.    else
  958.       locf = opt.output_document;
  959.  
  960.    count = 0;
  961.    
  962.    if (con->st & ON_YOUR_OWN)
  963.       con->st = ON_YOUR_OWN;
  964.  
  965.    orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
  966.  
  967.    /* THE loop. */
  968.    do
  969.    {
  970.       /* Increment the pass counter. */
  971.       ++count;
  972.       /* Wait before the retrieval (unless this is the very first
  973.      retrieval). */
  974.       if (!first_retrieval && opt.wait)
  975.      sleep(opt.wait);
  976.       if (first_retrieval)
  977.      first_retrieval = 0;
  978.       if (con->st & ON_YOUR_OWN)
  979.       {
  980.      con->cmd = 0;
  981.      con->cmd |= (DO_RETR | LEAVE_PENDING);
  982.      if (con->fd != -1)
  983.         con->cmd &= ~(DO_LOGIN | DO_CWD);
  984.      else
  985.         con->cmd |= (DO_LOGIN | DO_CWD);
  986.       }
  987.       else /* not on your own */
  988.       {
  989.      if (con->fd != -1)
  990.         con->cmd &= ~DO_LOGIN;
  991.      else
  992.         con->cmd |= DO_LOGIN;
  993.      if (con->st & DONE_CWD)
  994.         con->cmd &= ~DO_CWD;
  995.      else
  996.         con->cmd |= DO_CWD;
  997.       }
  998.       /* Assume no restarting. */
  999.       restval = 0L;
  1000.       if ((count > 1 || opt.always_rest)
  1001.       && !(con->cmd & DO_LIST)
  1002.       && exists(u->local))
  1003.      if (stat(u->local, &st) == 0)
  1004.         restval = st.st_size;
  1005.       /* Get the current time string. */
  1006.       tms = time_str(NULL);
  1007.       /* Print fetch message, if opt.verbose. */
  1008.       if (opt.verbose)
  1009.       {
  1010.      char *hurl = str_url(u->proxy ? u->proxy : u, 1);
  1011.      char tmp[15];
  1012.      strcpy(tmp, "        ");
  1013.      if (count > 1)
  1014.         sprintf(tmp, "(try:%2d)", count);
  1015.      fprintf(opt.lfile,
  1016.          "--%s--  %s\n  %s => `%s'\n",
  1017.          tms, hurl, tmp, locf);
  1018.      free(hurl);
  1019.       }
  1020.       /* Send getftp the proper length, if fileinfo was provided. */
  1021.       if (f)
  1022.      len = f->size;
  1023.       else
  1024.      len = 0;
  1025.       err = getftp(u, &len, restval, con);
  1026.       /* Time? */
  1027.       tms = time_str(NULL);
  1028.       tmrate = rate(len - restval, con->dltime);
  1029.       
  1030.       if (con->fd == -1)
  1031.      con->st &= ~DONE_CWD;
  1032.       else
  1033.      con->st |= DONE_CWD;
  1034.       
  1035.       switch (err)
  1036.       {
  1037.      case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
  1038.      case FTPNSFOD: case FTPLOGINC: case FTPNOPASV:
  1039.         /* Fatal errors, give up. */
  1040.         return err;
  1041.         break;
  1042.      case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
  1043.      case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
  1044.      case BINDERR: case LISTENERR: case ACCEPTERR:
  1045.      case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
  1046.         printwhat(count, opt.ntry);
  1047.         /* Non-fatal errors */
  1048.         continue;
  1049.         break;
  1050.      case FTPRETRINT:
  1051.         /* If the control connection was closed, the retrieval
  1052.            will be considered OK if f->size == len. */
  1053.         if (!f || len != f->size)
  1054.         {
  1055.            printwhat(count, opt.ntry);
  1056.            continue;
  1057.         }
  1058.         break;
  1059.      case RETRFINISHED:
  1060.         /* great! */
  1061.         break;
  1062.      default:
  1063.         /* not-so-great */
  1064.         assert(0);
  1065.       }
  1066.       if (con->st & ON_YOUR_OWN)
  1067.       {
  1068.      CLOSE(con->fd);
  1069.      con->fd = -1;
  1070.       }
  1071.       if (opt.verbose)
  1072.      fprintf(opt.lfile, "%s (%s) - `%s' saved [%ld]\n\n",
  1073.          tms, tmrate, locf, len);
  1074.       else if (!opt.quiet)
  1075.      fprintf(opt.lfile, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
  1076.          tms, u->url, len, locf, count);
  1077.       /* Do not count listings among the downloaded stuff, since they
  1078.      will get deleted anyway. */
  1079.       if (!(con->cmd & DO_LIST))
  1080.       {
  1081.      ++opt.numurls;
  1082.      opt.downloaded += len;
  1083.       }
  1084.       /* Restore the original leave-pendingness. */
  1085.       if (orig_lp)
  1086.      con->cmd |= LEAVE_PENDING;
  1087.       else
  1088.      con->cmd &= ~LEAVE_PENDING;
  1089.       return RETROK;
  1090.    } while (!opt.ntry || (count < opt.ntry));
  1091.    
  1092.    if (con->fd && (con->st & ON_YOUR_OWN))
  1093.    {
  1094.       CLOSE(con->fd);
  1095.       con->fd = -1;
  1096.    }
  1097.    return TRYLIMEXC;
  1098. }
  1099.  
  1100. /* Return the directory listing in a reusable format. The directory is
  1101.    speicifed in u->dir. */
  1102. struct fileinfo *
  1103. ftp_get_listing(urlinfo *u, ccon *con)
  1104. {
  1105.    struct fileinfo *f;
  1106.    uerr_t err;
  1107.    char *olocal = u->local;
  1108.    char *list_filename, *ofile;
  1109.    
  1110.    con->st &= ~ON_YOUR_OWN;
  1111.    con->cmd |= (DO_LIST | LEAVE_PENDING);
  1112.    con->cmd &= ~DO_RETR;
  1113.    /* Get the listing filename. */
  1114.    ofile = u->file;
  1115.    u->file = LIST_FILENAME;
  1116.    list_filename = url_filename(u);
  1117.    u->file = ofile;
  1118.    u->local = list_filename;
  1119. #ifdef DEBUG
  1120.    if (opt.debug)
  1121.       fprintf(opt.lfile, "Using `%s' as listing tmp file.\n", list_filename);
  1122. #endif
  1123.    err = ftp_loop_internal(u, NULL, con);
  1124.    u->local = olocal;
  1125.    if (err == RETROK)
  1126.       f = ftp_parse_ls(list_filename);
  1127.    else
  1128.       f = NULL;
  1129.    if (opt.remove_listing)
  1130.    {
  1131.       if (unlink(list_filename))
  1132.       {
  1133.      if (!opt.quiet)
  1134.         fprintf(opt.lfile, "unlink: %s\n", mystrerror(errno));
  1135.       }
  1136.       else if (opt.verbose)
  1137.      fprintf(opt.lfile, "Removed `%s'.\n", list_filename);
  1138.    }
  1139.    free(list_filename);
  1140.    con->cmd &= ~DO_LIST;
  1141.    return f;
  1142. }
  1143.  
  1144. /* Retrieve a list of files given in struct fileinfo linked list. If a
  1145.    file is a symbolic link, do not retrieve it, but rather try to set
  1146.    up a similar link on the local disk, if the symlinks are supported.
  1147.  
  1148.    If opt.recursive is set, after all files have been retrieved,
  1149.    ftp_retrieve_dirs will be called to retrieve the directories. */
  1150. uerr_t
  1151. ftp_retrieve_list(urlinfo *u, struct fileinfo *f, ccon *con)
  1152. {
  1153.    void my_touch PARAMS((char *, time_t));
  1154.    static int depth = 0;
  1155.    uerr_t err;
  1156.    char *olocal, *ofile;
  1157.    struct fileinfo *orig;
  1158.    long local_size;
  1159.    time_t tml;
  1160.    int dlthis;
  1161.  
  1162.    /* Increase the depth. */
  1163.    ++depth;
  1164.    if (opt.maxreclevel && depth > opt.maxreclevel)
  1165.    {
  1166. #ifdef DEBUG
  1167.       if (opt.debug)
  1168.      fprintf(opt.lfile, "Recursion depth %d exceeded max. depth %d.\n",
  1169.          depth, opt.maxreclevel);
  1170. #endif
  1171.       --depth;
  1172.       return RECLEVELEXC;
  1173.    }
  1174.  
  1175.    assert(f != NULL);
  1176.    orig = f;
  1177.  
  1178.    con->st &= ~ON_YOUR_OWN;
  1179.    if (!(con->st & DONE_CWD))
  1180.       con->cmd |= DO_CWD;
  1181.    else
  1182.       con->cmd &= ~DO_CWD;
  1183.    con->cmd |= (DO_RETR | LEAVE_PENDING);
  1184.    
  1185.    if (con->fd == -1)
  1186.       con->cmd |= DO_LOGIN;
  1187.    else
  1188.       con->cmd &= ~DO_LOGIN;
  1189.  
  1190.    err = RETROK;                /* In case it's not used. */
  1191.    
  1192.    while (f)
  1193.    {
  1194.       if (opt.quota && opt.downloaded > opt.quota)
  1195.       {
  1196.      --depth;
  1197.      return QUOTEXC;
  1198.       }
  1199.       olocal = u->local;
  1200.       ofile = u->file;
  1201.       u->file = f->name;
  1202.       u->local = url_filename(u);
  1203.       err = RETROK;
  1204.  
  1205.       dlthis = 1;
  1206.       if (opt.timestamping && f->type == PLAINFILE)
  1207.       {
  1208.      struct stat st;
  1209.      if (!stat(u->local, &st))
  1210.      {
  1211.         /* Else, get it from the file. */
  1212.         local_size = st.st_size;
  1213.         tml = st.st_mtime;
  1214.         if (local_size == f->size && tml >= f->tstamp)
  1215.         {
  1216.            if (opt.verbose)
  1217.           fprintf(opt.lfile, "Local file `%s' is more recent, not retrieving.\n\n", u->local);
  1218.            dlthis = 0;
  1219.         }
  1220.         else if (local_size != f->size)
  1221.         {
  1222.            if (opt.verbose)
  1223.           fprintf(opt.lfile, "The sizes do not match (local %ld), retrieving.\n", local_size);
  1224.         }
  1225.      }
  1226.       }    /* opt.timestamping && f->type == PLAINFILE */
  1227.       switch (f->type)
  1228.       {
  1229.      case SYMLINK:
  1230.         /* If opt.retr_symlinks is defined, we treat symlinks as
  1231.            if they were normal files.  There is currently no way
  1232.            to distinguish whether they might be directories, and
  1233.            follow them. */
  1234.         if (!opt.retr_symlinks)
  1235.         {
  1236. #ifdef HAVE_SYMLINK
  1237.            if (!f->linkto)
  1238.            {
  1239.           if (!opt.quiet)
  1240.              fprintf(opt.lfile, "Invalid name of the symlink, skipping.\n");
  1241.            }
  1242.            else             /* have f->linkto */
  1243.            {
  1244.           if (*f->linkto != '/')
  1245.           {
  1246.              if (opt.verbose)
  1247.             fprintf(opt.lfile, "Creating symlink %s -> %s\n",
  1248.                 u->local, f->linkto);
  1249.              unlink(u->local); /* Unlink before creating symlink! */
  1250.              if (symlink(f->linkto, u->local) == -1)
  1251.              {
  1252.             if (!opt.quiet)
  1253.                fprintf(opt.lfile, "symlink: %s\n", mystrerror(errno));
  1254.              }
  1255.              fputc('\n', opt.lfile);
  1256.           }
  1257.           else
  1258.           {
  1259.              if (!opt.quiet)
  1260.             fprintf(opt.lfile, "Will not create symlink `%s'.\n", f->linkto);
  1261.           }
  1262.            } /* have f->linkto */
  1263. #else  /* not HAVE_SYMLINK */
  1264.            if (!opt.quiet)
  1265.           fprintf(opt.lfile,
  1266.               "Symlinks not supported, skipping symlink `%s'.\n",
  1267.               u->local);
  1268. #endif /* not HAVE_SYMLINK */
  1269.         }
  1270.         else                /* opt.retr_symlinks */
  1271.         {
  1272.            if (dlthis)
  1273.           err = ftp_loop_internal(u, f, con);
  1274.         } /* opt.retr_symlinks */
  1275.         break;
  1276.      case DIRECTORY:
  1277.         if (!opt.recursive)
  1278.            fprintf(opt.lfile, "Skipping directory `%s'.\n", f->name);
  1279.         break;
  1280.      case PLAINFILE:
  1281.         /* Call the retrieve loop! */
  1282.         if (dlthis)
  1283.            err = ftp_loop_internal(u, f, con);
  1284.         break;
  1285.      case UNKNOWN:
  1286.         if (!opt.quiet)
  1287.            fprintf(opt.lfile, "%s: unknown/unsupported file type.\n", f->name);
  1288.         break;
  1289.       }    /* switch */
  1290.  
  1291.       /* Set the time-stamp information to the local file. Symlinks
  1292.      are not to be stamped because it sets the stamp on the
  1293.      original. :( */
  1294.       if (!opt.dfp
  1295.       && !(f->type == SYMLINK && !opt.retr_symlinks)
  1296.       && f->tstamp != -1
  1297.       && exists(u->local))
  1298.       {
  1299.      my_touch(u->local, f->tstamp);
  1300.       }
  1301.       else if (f->tstamp == -1)
  1302.       {
  1303.      if (!opt.quiet)
  1304.         fprintf(opt.lfile, "%s: corrupt time-stamp.\n", u->local);
  1305.       }
  1306.  
  1307.       free(u->local);
  1308.       u->local = olocal;
  1309.       u->file = ofile;
  1310.       if (err != RETROK)
  1311.      break;
  1312.       con->cmd &= ~(DO_CWD | DO_LOGIN);
  1313.       f = f->next;
  1314.    } /* while */
  1315.    /* We do not want to call ftp_retrieve_dirs here */
  1316.    if (opt.recursive && !(opt.maxreclevel && depth >= opt.maxreclevel))
  1317.        err = ftp_retrieve_dirs(u, orig, con);
  1318.    else if (opt.recursive)
  1319.    {
  1320. #ifdef DEBUG
  1321.       if (opt.debug)
  1322.      fprintf(opt.lfile,
  1323.          "Will not retrieve dirs since depth is %d (max %d).\n",
  1324.          depth, opt.maxreclevel);
  1325. #endif
  1326.    }
  1327.    --depth;
  1328.    return err;
  1329. }
  1330.  
  1331. /* Retrieve the directories given in a file list.  This function works
  1332.    by simply going through the linked list and calling
  1333.    ftp_retrieve_glob on each directory entry.  The function knows
  1334.    about excluded directories.  */
  1335. uerr_t
  1336. ftp_retrieve_dirs(urlinfo *u, struct fileinfo *f, ccon *con)
  1337. {
  1338.    char *odir;
  1339.    int l;
  1340.    
  1341.    for (; f; f = f->next)
  1342.    {
  1343.       if (opt.quota && opt.downloaded > opt.quota)
  1344.      break;
  1345.       if (f->type != DIRECTORY)
  1346.      continue;
  1347.       odir = u->dir;
  1348.       l = strlen(u->dir);
  1349.       u->dir = nmalloc(1 + l + 1 + strlen(f->name) + 1);
  1350.       /* When retrieving recursively, all directories must be
  1351.      absolute. This restriction will be lifted in the future. */
  1352.       sprintf(u->dir, "/%s%s%s", odir + (*odir == '/'),
  1353.           (!*odir || (*odir == '/' && !*(odir + 1))) ? "" : "/", f->name);
  1354.       if (!accdir(u->dir, ALLABS))
  1355.       {
  1356.      if (opt.verbose)
  1357.         fprintf(opt.lfile, "Not descending to `%s' as it is excluded/not-included.\n",
  1358.             u->dir);
  1359.      free(u->dir);
  1360.      u->dir = odir;
  1361.      continue;
  1362.       }
  1363.       con->st &= ~DONE_CWD;
  1364.       ftp_retrieve_glob(u, con, GETALL);
  1365.       /* Set the time-stamp? */
  1366.       free(u->dir);
  1367.       u->dir = odir;
  1368.    }
  1369.    if (opt.quota && opt.downloaded > opt.quota)
  1370.       return QUOTEXC;
  1371.    else
  1372.       return RETROK;
  1373. }
  1374.  
  1375.  
  1376. /* A near-top-level function to retrieve the files in a directory.
  1377.    The function calls ftp_get_listing, to get a linked list of
  1378.    files. Then it weeds out the file names that do not match the
  1379.    pattern.  ftp_retrieve_list is called with this updated list as an
  1380.    argument.
  1381.  
  1382.    If the argument ACTION is GETONE, just download the file (but first
  1383.    get the listing, so that the time-stamp is heeded); if it's GLOBALL,
  1384.    use globbing' if it's GETALL, download the whole directory.  */
  1385. uerr_t
  1386. ftp_retrieve_glob(urlinfo *u, ccon *con, int action)
  1387. {
  1388.    struct fileinfo *f, *orig, *start;
  1389.    int matchres;
  1390.    uerr_t res;
  1391.  
  1392.    con->cmd |= LEAVE_PENDING;
  1393.    
  1394.    orig = ftp_get_listing(u, con);
  1395.    start = orig;
  1396.    /* First: weed out that do not conform the global rules given in
  1397.       opt.accepts and opt.rejects. */
  1398.    if (opt.accepts || opt.rejects)
  1399.    {
  1400.       f = orig;
  1401.       while (f)
  1402.       {
  1403.      if (f->type != DIRECTORY && !acceptable(f->name))
  1404.      {
  1405.         if (opt.verbose)
  1406.            fprintf(opt.lfile, "Rejecting `%s'.\n", f->name);
  1407.         f = delelement(f, &start);
  1408.      }
  1409.      else
  1410.         f = f->next;
  1411.       }
  1412.    }
  1413.    /* Now weed out the files that do not match our globbing pattern.
  1414.       If we are dealing with a globbing pattern, that is. */
  1415.    if (*u->file && (action == GLOBALL || action == GETONE))
  1416.    {
  1417.       matchres = 0;
  1418.       f = start;
  1419.       while (f)
  1420.       {
  1421.      matchres = fnmatch(u->file, f->name, 0);
  1422.      if (matchres == -1)
  1423.      {
  1424.         if (!opt.quiet)
  1425.            fprintf(opt.lfile, "%s: %s\n", u->local, mystrerror(errno));
  1426.         break;
  1427.      }
  1428.      if (matchres == FNM_NOMATCH)
  1429.         f = delelement(f, &start); /* Delete the element from the list. */
  1430.      else
  1431.         f = f->next;        /* Leave the element in the list. */
  1432.       }
  1433.       if (matchres == -1)
  1434.       {
  1435.      freefileinfo(start);
  1436.      return RETRBADPATTERN;
  1437.       }
  1438.    }
  1439.    res = RETROK;
  1440.    if (start)
  1441.    {
  1442.       /* Just get everything.  */
  1443.       ftp_retrieve_list(u, start, con);
  1444.    }
  1445.    else if (!start)
  1446.    {
  1447.       if (action == GLOBALL)
  1448.       {
  1449.      /* No luck.  */
  1450.      if (opt.verbose)
  1451.         fprintf(opt.lfile, "No matches on pattern `%s'.\n", u->file);
  1452.       }
  1453.       else /* GETONE or GETALL */
  1454.       {
  1455.      /* Let's try retrieving it anyway.  */
  1456.      con->st |= ON_YOUR_OWN;
  1457.      res = ftp_loop_internal(u, NULL, con);
  1458.      return res;
  1459.       }
  1460.    }
  1461.    freefileinfo(start);
  1462.    if (opt.quota && opt.downloaded > opt.quota)
  1463.       return QUOTEXC;
  1464.    else
  1465.       return RETROK;
  1466. }
  1467.  
  1468. /* The wrapper that calls an appropriate routine according to contents
  1469.    of URL. Inherently, its capabilities are limited on what can be
  1470.    encoded into a URL. */
  1471. uerr_t
  1472. ftp_loop(urlinfo *u, int *dt)
  1473. {
  1474.    ccon con;                    /* FTP connection. */
  1475.    uerr_t res;
  1476.    struct fileinfo *f;
  1477.  
  1478.    *dt = 0;
  1479.  
  1480.    con.fd = -1;
  1481.    con.st = ON_YOUR_OWN;
  1482.    res = RETROK;        /* In case it's not used. */
  1483.  
  1484.    /* If the file name is empty, the user probably wants a directory
  1485.       index. Wel'll provide one, properly HTML-ized.  Unless
  1486.       opt.htmlify is 0, of course. :-) */
  1487.    if (!*u->file && !opt.recursive)
  1488.    {
  1489.       f = ftp_get_listing(u, &con);
  1490.       if (f)
  1491.       {
  1492.      if (opt.htmlify)
  1493.      {
  1494.         char *filename;
  1495.         filename = url_filename(u);
  1496.         res = ftp_index(filename, u, f);
  1497.         if (res == FTPOK && opt.verbose)
  1498.         {
  1499.            struct stat st;
  1500.            long sz;
  1501.            if (stat(filename, &st) == 0)
  1502.           sz = st.st_size;
  1503.            else
  1504.           sz = -1;
  1505.            fprintf(opt.lfile, "Wrote HTML-ized index to `%s' [%ld].\n",
  1506.                filename, (long)st.st_size);
  1507.         }
  1508.         free(filename);
  1509.      }
  1510.      freefileinfo(f);
  1511.       }
  1512.    }
  1513.    else
  1514.    {
  1515.       int wild = has_wildcards(u->file);
  1516.       if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
  1517.       {
  1518.      /* ftp_retrieve_glob is a catch-all function that gets called
  1519.         if we need globbing, time-stamping or recursion.  Its
  1520.         third argument is just what we really need.  */
  1521.      ftp_retrieve_glob(u, &con, (opt.ftp_glob && wild) ? GLOBALL : GETONE);
  1522.       }
  1523.       else
  1524.      res = ftp_loop_internal(u, NULL, &con);
  1525.    }
  1526.    if (res == FTPOK)
  1527.       res = RETROK;
  1528.    if (res == RETROK)
  1529.       *dt |= RETROKF;
  1530.    /* If a connection was left, quench it. */
  1531.    if (con.fd != -1)
  1532.       CLOSE(con.fd);
  1533.    return res;
  1534. }
  1535.  
  1536. /* Deletes an element from the fileinfo linked list. Returns the
  1537.    address of the next element, or NULL if the list is exhausted. It
  1538.    can modify the start of the list. */
  1539. struct fileinfo *
  1540. delelement(struct fileinfo *f, struct fileinfo **start)
  1541. {
  1542.    struct fileinfo *prev, *next;
  1543.    
  1544.    prev = f->prev;
  1545.    next = f->next;
  1546.    if (next)
  1547.       next->prev = prev;
  1548.    if (!prev)
  1549.    {
  1550.       *start = next;
  1551.       if (!next)
  1552.      return NULL;
  1553.       free(f->name);
  1554.       if (f->linkto)
  1555.      free(f->linkto);
  1556.       free(f);
  1557.    }
  1558.    else
  1559.       prev->next = next;
  1560.    return next;
  1561. }
  1562.  
  1563. /* Free the fileinfo linked list of files. */
  1564. void
  1565. freefileinfo(struct fileinfo *f)
  1566. {
  1567.    struct fileinfo *p;
  1568.  
  1569.    while (f)
  1570.    {
  1571.       p = f->next;
  1572.       free(f->name);
  1573.       if (f->linkto)
  1574.      free(f->linkto);
  1575.       free(f);
  1576.       f = p;
  1577.    }
  1578. }
  1579.  
  1580.